/**
 *  \file I3Packet.h
 *  \brief Defines the format of packets sent out and received by the I3OCD.
 *  This is different from the actual i3 packets which are at a lower level.
 */

#ifndef I3_PACKET_H
#define I3_PACKET_H 1

#include "OCD_include.h"


extern "C" {
    #include "i3.h"
}

#define DEFAULT_SERVER_PROXY_TRIGGER_LEN 24

#define I3_PROXY_HDR_LEN   (ID_LEN + 2)

//Fields used inside an i3 packet
//The second byte is one of the following

/** This block is to be passed on to the proxy
  * and is not to be interpreted by the i3 module.
  */
#define I3_BLOCK_GENERIC                0x00

/** Private trigger request only */
#define I3_BLOCK_PRIVATE_TRIG_REQ      0x01

/** Private trigger only confirmation */
#define I3_BLOCK_PRIVATE_TRIG_CNF      0x02

#define I3_BLOCK_PRIVATE_TRIG_REMOVE   0x03
#define I3_BLOCK_DATA                  0x04
#define I3_BLOCK_PUBLIC_TRIG_REQ       0x05
#define I3_BLOCK_PUBLIC_TRIG_CNF       0x05
#define I3_BLOCK_AUTH_PRIVATE_TRIG_REQ 0x06
#define I3_BLOCK_FAKE_REMOVE           0x07
#define I3_BLOCK_LEGACY_DNS_ERROR      0x08

/**
  * This represents a private trigger request made for a particular 
  * URL to a server proxy.
  */
#define I3_BLOCK_PRIVATE_TRIG_REQ_VIA_SERVER_PROXY   0x09

/**
  * This denotes a data packet sent to a public trigger
  * (as against normal data packets which are sent to private triggers)
  */
#define I3_BLOCK_DATA_VIA_PUB_TRIG     0x0A

#define I3_BLOCK_GENERIC_VIA_PUB_TRIG 0x0B

/**
  * This class defines a generic I3 packet. 
  */
class I3Packet {
public:
    /** The length of the packet */
    unsigned short len;         

    /** Pointer to the contents of the packet */
    char *pktContents;
};

/** Generic I3 Packet Block */
typedef struct {

    /** This can imply that this is one of the i3 specific blocks
     *  or it is a generic block to be handed off to the proxy.
     */
    uint8_t blockType;
    
    /** Offset to the start of the next block from the start of this block.
      * A value of 0 implies that there is no nextBlock.
      */
    uint16_t nextBlock;

    uint8_t piggybackLen;
} I3Block;

/** This represents a block to be processed by the generic proxy
  * and not by i3.
  */
typedef struct {

    I3Block headerBlock;

    /** This is just a way to refer to the generic block.  No memory is actually allocated. */
    char genericBlock[0];

} I3GenericBlock;

/** This represents a block to be processed by the generic proxy
  * and not by i3.  This block is used when sending to the public trigger.
  */
typedef struct {

    I3Block headerBlock;

    /** The private id of the machine sending this data block. */
    ID senderPrivId;
    
    /** This is just a way to refer to the generic block.  No memory is actually allocated. */
    char genericBlock[0];

} I3GenericBlockViaPubTrig;

/**
  * This block carries data meant for the legacy application.
  * This data block is sent to the private trigger of the remote host.
  */
typedef struct {

    I3Block headerBlock;
    
    /** Length of the actual data */
    uint16_t dataLen;

    /** This is just a pointer to the data. No memory is allocated for this field */
    char data[0];
    
} I3DataBlock;

/**
  * A private trigger request block.
  * blockType = I3_BLOCK_PRIV_TRIG_REQ
  */
typedef struct {

    I3Block headerBlock;

    /** The senders private id.  The reply is sent to this private id */
    ID senderPrivId;

    /** If this flag is true, the remote end point will change
      * the status of the VN, created on receipt of this request, to READY
      * even before the private trigger is inserted.
      */
    bool enableFastConnectionSetup;

    /** This will contain the requested URL name along with its 
      * preferences.
      */
    char dnsPrefStr [ MAX_PREF_STRING_LEN];
    
} I3PrivateTriggerRequest;

/**
  * This represents a private trigger request made to a server proxy.
  * This block will have the requested URL in addition to the fields
  * of I3PrivateTriggerRequest.
  */
typedef struct {

    I3Block headerBlock;

    /** The senders private id.  The reply is sent to this private id */
    ID senderPrivId;

    /** The URL of the connection requested to the server proxy */
    char requestedURL[MAX_URL_LEN]; 
    
} I3PrivateTriggerRequestViaServerProxy;


/**
  * A private trigger reply.
  * blockType = I3_BLOCK_PRIV_TRIG_CNF
  */
typedef struct {
    I3Block headerBlock;
    
    /** The requested private trigger id */
    ID privTrigId;
    
} I3PrivateTriggerReply;


#endif
